-------------------------------------------------------------------------------
--exp_sig_gen
--Created (25.08.2011)
--Created by Alina Ivanova
--Modified (date, by whom)
--Version 1.0
--test exponentional signal generator
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
-- VHDL exp_sig_gen
-------------------------------------------------------------------------------
library ieee;
use     ieee.std_logic_1164.all;
use     ieee.std_logic_unsigned.all;
use     work.package_settings.all;

library altera_mf;
use altera_mf.all;

entity exp_sig_gen is
	port(
		reset                                                   : in  std_logic;
		clk                                                     : in  std_logic;
-------------------------------------------------------------------------------
		overlay                                                 : in  std_logic;
		rate                                                    : in  std_logic;
		delay                                                   : in  std_logic_vector (SIZE_DELAY downto 0);
-------------------------------------------------------------------------------
		output_data                                             : out std_logic_vector (SIZE_ADC_DATA downto 0));
end exp_sig_gen;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture functional of exp_sig_gen is
	signal rom_data_out                                        : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal ram1_q                                              : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal data_ram2                                           : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal ram2_q                                              : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal ram_addr                                            : std_logic_vector (SIZE_DELAY downto 0);

	signal dataShift                                           : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal rm_addr                                             : std_logic_vector (SIZE_TEST_COUNTER downto 0);
	signal dataOverlay                                         : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal data_last                                           : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal reset_ram                                           : std_logic;

	signal adder_1                                             : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal adder_2                                             : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal result_add_1                                        : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal result_add_2                                        : std_logic_vector (SIZE_ADC_DATA downto 0);
	signal reset_adder                                         : std_logic;

	component rom_exp_sig_gen
		port(
			address                                              : in  std_logic_vector (SIZE_TEST_RAM_ADDR+2 downto 0);
			clock                                                : in  std_logic:= '1';
			q                                                    : out std_logic_vector (SIZE_ADC_DATA downto 0));
	end component;
	component ram_exp_sig_gen
		port(
			aclr                                                 : in  std_logic:= '0';
			clock                                                : in  std_logic:= '1';
			data                                                 : in  std_logic_vector (SIZE_ADC_DATA downto 0);
			rdaddress                                            : in  std_logic_vector (SIZE_DELAY downto 0);
			rden                                                 : in  std_logic:= '1';
			wraddress                                            : in  std_logic_vector (SIZE_DELAY downto 0);
			wren                                                 : in  std_logic:= '0';
			q                                                    : out std_logic_vector (SIZE_ADC_DATA downto 0));
	end component;
	component add_exp_sig_gen
		port(
			aclr                                                 : in  std_logic;
			clock                                                : in  std_logic;
			dataa                                                : in  std_logic_vector (SIZE_ADC_DATA DOWNTO 0);
			datab                                                : in  std_logic_vector (SIZE_ADC_DATA DOWNTO 0);
			result                                               : out std_logic_vector (SIZE_ADC_DATA DOWNTO 0));
	end component;
begin
	RomExpSigGen: rom_exp_sig_gen port map(
		address                                                 => rm_addr(SIZE_TEST_RAM_ADDR+2 downto 0),
		clock                                                   => clk,
		q                                                       => rom_data_out);
	RamExpSigGen1: ram_exp_sig_gen port map(
		aclr                                                    => reset_ram,
		clock                                                   => clk,
		data                                                    => dataShift,
		rdaddress                                               => ram_addr,
		rden                                                    => '1',
		wraddress                                               => rm_addr(SIZE_DELAY downto 0),
		wren                                                    => '1',
		q                                                       => ram1_q);
	RamExpSigGen2: ram_exp_sig_gen port map(
		aclr                                                    => reset_ram,
		clock                                                   => clk,
		data                                                    => data_ram2,
		rdaddress                                               => ram_addr,
		rden                                                    => '1',
		wraddress                                               => rm_addr(SIZE_DELAY downto 0),
		wren                                                    => '1',
		q                                                       => ram2_q);
	AddExpSigGen1: add_exp_sig_gen port map(
		aclr                                                    => reset_adder,
		clock                                                   => clk,
		dataa                                                   => adder_1,
		datab                                                   => adder_2,
		result                                                  => result_add_1);
	AddExpSigGen2: add_exp_sig_gen port map(
		aclr                                                    => reset_adder,
		clock                                                   => clk,
		dataa                                                   => result_add_1,
		datab                                                   => dataShift,
		result                                                  => result_add_2);

	output_data                                               <= data_last;
	reset_ram                                                 <= not reset;

	reset_adder                                               <= not overlay;
	Process_1: process (clk, reset, rm_addr, delay, overlay, rate)
	begin
		if (reset = '0') then
			dataShift                                           <= (others => '0');
			rm_addr                                             <= (others => '0');
			dataOverlay                                         <= (others => '0');
			data_last                                           <= (others => '0');
			ram_addr                                            <= (others => '0');
			data_ram2                                           <= (others => '0');
			adder_1                                             <= (others => '0');
			adder_2                                             <= (others => '0');
		elsif (rising_edge(clk)) then
			adder_1           <= "00" & ram1_q(SIZE_ADC_DATA downto 2);
			adder_2           <= "000" & ram2_q(SIZE_ADC_DATA downto 3);
			if (rm_addr(SIZE_DELAY downto 0) < delay + 3) then
				ram_addr      <= (others => '0');
				data_ram2     <= (others => '0');
			elsif(rm_addr(SIZE_DELAY downto 0) >= delay + 3) then
				ram_addr      <= (rm_addr(SIZE_DELAY downto 0) - delay);
				data_ram2     <= ram1_q;
			end if;
			rm_addr           <= rm_addr + 1;
			if (rate = '1') then
--				case rm_addr(11 downto 8) is
--					when "0000" => dataShift <= (rom_data_out(SIZE_ADC_DATA downto 0));
--					when "0001" => dataShift <= ("0" & rom_data_out(SIZE_ADC_DATA downto 1));
--					when "0010" => dataShift <= ("00" & rom_data_out(SIZE_ADC_DATA downto 2));
--					when "0011" => dataShift <= ("000" & rom_data_out(SIZE_ADC_DATA downto 3));
--					when "0100" => dataShift <= ("0000" & rom_data_out(SIZE_ADC_DATA downto 4));
--					when "0101" => dataShift <= ("00000" & rom_data_out(SIZE_ADC_DATA downto 5));
--					when "0110" => dataShift <= ("000000" & rom_data_out(SIZE_ADC_DATA downto 6));
--					when "0111" => dataShift <= ("0000000" & rom_data_out(SIZE_ADC_DATA downto 7));
--					when "1000" => dataShift <= ("0000000" & rom_data_out(SIZE_ADC_DATA downto 7));
--					when "1001" => dataShift <= ("000000" & rom_data_out(SIZE_ADC_DATA downto 6));
--					when "1010" => dataShift <= ("00000" & rom_data_out(SIZE_ADC_DATA downto 5));
--					when "1011" => dataShift <= ("0000" & rom_data_out(SIZE_ADC_DATA downto 4));
--					when "1100" => dataShift <= ("000" & rom_data_out(SIZE_ADC_DATA downto 3));
--					when "1101" => dataShift <= ("00" & rom_data_out(SIZE_ADC_DATA downto 2));
--					when "1110" => dataShift <= ("0" & rom_data_out(SIZE_ADC_DATA downto 1));
--					when "1111" => dataShift <= (rom_data_out(SIZE_ADC_DATA downto 0));
--					when others => dataShift <= (rom_data_out(SIZE_ADC_DATA downto 0));
--				end case;

				if (rm_addr(11 downto 8) = "0000") then
					dataShift <= (rom_data_out(SIZE_ADC_DATA downto 0));
				elsif (rm_addr(11 downto 8) = "0001") then
					dataShift <= ("0" & rom_data_out(SIZE_ADC_DATA downto 1));
				elsif (rm_addr(11 downto 8) = "0010") then
					dataShift <= ("00" & rom_data_out(SIZE_ADC_DATA downto 2));
				elsif (rm_addr(11 downto 8) = "0011") then
					dataShift <= ("000" & rom_data_out(SIZE_ADC_DATA downto 3));
				elsif (rm_addr(11 downto 8) = "0100") then
					dataShift <= ("0000" & rom_data_out(SIZE_ADC_DATA downto 4));
				elsif (rm_addr(11 downto 8) = "0101") then
					dataShift <= ("00000" & rom_data_out(SIZE_ADC_DATA downto 5));
				elsif (rm_addr(11 downto 8) = "0110") then
					dataShift <= ("000000" & rom_data_out(SIZE_ADC_DATA downto 6));
				elsif (rm_addr(11 downto 8) = "0111") then
					dataShift <= ("0000000" & rom_data_out(SIZE_ADC_DATA downto 7));
				elsif (rm_addr(11 downto 8) = "1000") then
					dataShift <= ("0000000" & rom_data_out(SIZE_ADC_DATA downto 7));
				elsif (rm_addr(11 downto 8) = "1001") then
					dataShift <= ("000000" & rom_data_out(SIZE_ADC_DATA downto 6));
				elsif (rm_addr(11 downto 8) = "1010") then
					dataShift <= ("00000" & rom_data_out(SIZE_ADC_DATA downto 5));
				elsif (rm_addr(11 downto 8) = "1011") then
					dataShift <= ("0000" & rom_data_out(SIZE_ADC_DATA downto 4));
				elsif (rm_addr(11 downto 8) = "1100") then
					dataShift <= ("000" & rom_data_out(SIZE_ADC_DATA downto 3));
				elsif (rm_addr(11 downto 8) = "1101") then
					dataShift <= ("00" & rom_data_out(SIZE_ADC_DATA downto 2));
				elsif (rm_addr(11 downto 8) = "1110") then
					dataShift <= ("0" & rom_data_out(SIZE_ADC_DATA downto 1));
				elsif (rm_addr(11 downto 8) = "1111") then
					dataShift <= (rom_data_out(SIZE_ADC_DATA downto 0));
				end if;
			else
				dataShift     <= (rom_data_out(SIZE_ADC_DATA downto 0));
			end if;
			if (overlay = '1') then
				if ((rm_addr(SIZE_DELAY downto 0) ) <= delay) then
					dataOverlay    <= dataShift;
				elsif ((rm_addr(SIZE_DELAY downto 0) ) > delay) then
					dataOverlay    <= result_add_2;
				end if;
			else
				dataOverlay    <= dataShift;
			end if;
			data_last          <= dataOverlay;
		end if;
	end process Process_1;
end functional;
-------------------------------------------------------------------------------
